home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Technology Seed / ADC Seed CD - July 1999.toast / Carbon SDK 1.0d10c3 / Sample Code / SimpleText / Clipboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-04  |  14.6 KB  |  552 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        Clipboard.c
  3.  
  4.     Contains:    Clipboard support for simple text application.
  5.  
  6.     Version:    SimpleText 1.4 or later
  7.  
  8.     Written by:    Tom Dowdy
  9.                 DAL = Dave Lyons
  10.  
  11.     Copyright:    © 1993-1997 by Apple Computer, Inc., all rights reserved.
  12.  
  13.     File Ownership:
  14.  
  15.         DRI:                Tom Dowdy
  16.  
  17.         Other Contact:        Jim Negrette
  18.  
  19.         Technology:            Macinotosh Graphics Group
  20.  
  21.     Writers:
  22.  
  23.         (dmp)    Dave Polaschek
  24.         (ted)    Tom Dowdy
  25.         (TD)    Tom Dowdy
  26.  
  27.     Change History (most recent first):
  28.  
  29.     $Log: Clipboard.c,v $
  30.     Revision 1.10  1999/05/01 01:52:24  jiarocci
  31.     Comment out grafprocs so we build against latest CarbonLib interfaces on 8.x.
  32.  
  33.     Revision 1.9  1999/02/16 00:41:37  christ
  34.     Integrate document proxy icon support
  35.  
  36.     Revision 1.8  1998/11/11 22:28:52  wilkes
  37.     Fixed various problems caused by the interface changes made by Nitin earlier,
  38.     mostly involving static RoutineDescriptors...
  39.     
  40.     Revision 1.7  1998/10/14 18:52:45  voas
  41.     Eliminate all warnings. Get working with top of tree.
  42.  
  43.     Revision 1.6  1998/09/15 18:59:42  jiarocci
  44.     SimpleText now builds with -DTARGET_CARBON=1. Still needs further cleanup.
  45.     
  46.     Revision 1.5  1998/09/12 23:07:57  voas
  47.     Use InvalWindowRect instead of InvalRect.
  48.  
  49.     Revision 1.4  1998/03/30 22:12:24  mkellner
  50.     Update to use new GetQDxxxx macros for qd.globals
  51.     
  52.     Revision 1.3  1998/03/21 04:13:11  mkellner
  53.     Add a define for qd_screenBits for qd.screenBits.
  54.     Replaced qd.screenBits with qd_screenBits
  55.     
  56.     Revision 1.2  1998/03/20 03:19:52  mkellner
  57.     change qd.thePort to FrontWindow()
  58.     add SysEnvirons
  59.     
  60.     Revision 1.1.1.1  1998/03/18 22:56:06  ivory
  61.     Initial checkin of SimpleText.
  62.     
  63.         
  64.         2     7/29/97 2:07 PM Tom Dowdy
  65.         Removed all of the old and boring refs
  66.         
  67.         1     7/28/97 11:11 AM Duane Byram
  68.         first added to Source Safe project
  69.  
  70.          <5>      9/9/96    dmp        staticfy local functions to eliminate warnings in MWC.
  71.          <4>     5/31/96    ted        spelling FAT correctly
  72.          <4>     5/31/96    ted        adding PPC, FAT, and NuKernel builds
  73.          <3>     11/2/95    ted        BlockMoveData
  74.          <2>     10/2/95    TD        adding support for SC compiler
  75.          <1>     8/21/95    TD        First checked in.
  76.          <8>      9/8/94    DAL        Added do-nothing routines ClipboardKeyEvent and
  77.                                     ClipboardGetBalloon, to avoid strange balloon & keypress message
  78.                                     for the Clipboard window.
  79.  
  80. */
  81.  
  82. #include "MacIncludes.h"
  83.  
  84. #include "Clipboard.h"
  85.  
  86.  
  87. // --------------------------------------------------------------------------------------------------------------
  88. // GLOBALS FOR THIS FILE ONLY
  89. // --------------------------------------------------------------------------------------------------------------
  90. static Handle            gScrapHandle;
  91. static long            gCurrentOffset;
  92. #if USE_QD_GRAFPROCS
  93. static CQDProcs            gSavedProcs;
  94. static CQDProcs                gMyProcs;
  95. static CQDProcs                gMyColorProcs;
  96. #endif
  97.  
  98. // --------------------------------------------------------------------------------------------------------------
  99. // INTERNAL ROUTINES
  100. // --------------------------------------------------------------------------------------------------------------
  101. static pascal void GetPICTData(Ptr dataPtr, short byteCount)
  102. /*
  103.     replacement for the QuickDraw bottleneck routine
  104. */
  105.     long    longCount = byteCount;
  106.     
  107.     BlockMoveData((*gScrapHandle)+gCurrentOffset, dataPtr, longCount);
  108.     gCurrentOffset += longCount;
  109.     
  110. } // GetPICTData
  111.  
  112.  
  113. // --------------------------------------------------------------------------------------------------------------
  114.  
  115. static OSErr DrawPictureFromHandleAndOffset(
  116.     Rect    * pWhereToDraw,            // draw picture at this location
  117.     Handle    sourceHandle,            // handle containing data
  118.     long    sourceOffset)            // offset within handle to start at
  119. {
  120.     static QDGetPicUPP gGetPICTData = NULL;
  121.     OSErr        anErr;
  122.     Rect        whereToDraw = *pWhereToDraw;
  123.     PicHandle    tempPict = (PicHandle) NewHandle(sizeof(Picture));
  124. #if USE_QD_GRAFPROCS
  125.     CGrafPtr    thePort = GetQDGlobalsThePort();
  126. #endif
  127.  
  128.     if (!gGetPICTData) {
  129.         gGetPICTData = NewQDGetPicProc(GetPICTData);
  130.     }
  131.     
  132.     anErr = MemError();
  133.     nrequire(anErr, FailedNewHandle);
  134.         
  135.     // calculate the rectangle in which to draw, save the picture header into
  136.     // our handle
  137.     {    
  138.     PicPtr    pPicture;
  139.     
  140.     pPicture = (PicPtr)((*sourceHandle) + sourceOffset);
  141.     whereToDraw.right = whereToDraw.left + pPicture->picFrame.right - pPicture->picFrame.left;
  142.     whereToDraw.bottom = whereToDraw.top + pPicture->picFrame.bottom - pPicture->picFrame.top;
  143.     BlockMoveData((Ptr)pPicture, (Ptr)*tempPict, sizeof(Picture));
  144.     }
  145.  
  146.     // store into globals for our GetPicProc in preparation for the draw
  147.     gScrapHandle = sourceHandle;
  148.     gCurrentOffset = sourceOffset + sizeof(Picture);
  149.  
  150. #if USE_QD_GRAFPROCS
  151.     // install our GetPic proc
  152.     SetStdCProcs(&gMyColorProcs);
  153.     gMyProcs.getPicProc = gGetPICTData;
  154.     gMyColorProcs.getPicProc = gGetPICTData;
  155.     GetPortGrafProcs(thePort, &gSavedProcs);
  156.     SetPortGrafProcs(thePort, &gMyColorProcs);
  157. #endif
  158.     
  159.     // Draw the picture
  160.     DrawPicture(tempPict, &whereToDraw);
  161.     
  162. #if USE_QD_GRAFPROCS
  163.     // remove our GetPic proc
  164.     GetPortGrafProcs(thePort, &gSavedProcs);
  165. #endif
  166.  
  167.     DisposeHandle((Handle)tempPict);
  168.     
  169. // FALL THROUGH EXCEPTION HANDLING
  170. FailedNewHandle:
  171.     return anErr;
  172.     
  173. } // DrawPictureFromHandleAndOffset
  174.  
  175.  
  176. //
  177. // Figure out the scrap type and offset
  178. //
  179. static long GetScrapTypeAndOffset( OSType * type, long * offset )
  180. {
  181.     short         i = 0;
  182.     ResType        scrapTypes[] = {'TEXT', 'PICT', '????'};
  183.     long        scrapResult = 0;
  184.  
  185.     while (scrapTypes[i] != '????')
  186.         {
  187.         scrapResult = GetScrap(nil, scrapTypes[i], offset);
  188.         if (scrapResult > 0)
  189.             {
  190.             *type = scrapTypes[i];
  191.             break;
  192.             }
  193.         ++i;
  194.         }
  195.     
  196.     return scrapResult;
  197. }
  198.  
  199. // --------------------------------------------------------------------------------------------------------------
  200. // OOP INTERFACE ROUTINES
  201. // --------------------------------------------------------------------------------------------------------------
  202. static OSErr    ClipboardUpdateWindow(WindowRef pWindow, WindowDataPtr pData)
  203. {
  204. #pragma unused (pData)
  205.  
  206.     OSErr        anErr;
  207.     FontInfo    theInfo;
  208.     long        scrapResult = 0;
  209.     long        offset;
  210.     ResType        validScrapType = '????';
  211.     Rect        topAreaRect;
  212.     Rect        bounds;
  213.     RgnHandle    oldClip = NewRgn();
  214.     Rect        eraseRect;
  215.     
  216.     GetWindowPortBounds( pWindow, &eraseRect );
  217.     
  218.     // clear out any data that was there before
  219.     GetClip(oldClip);
  220.     EraseRect(GetWindowPortBounds(pWindow, &bounds));
  221.     
  222.     // get that scrap!
  223.     anErr = LoadScrap();
  224.     nrequire(anErr, LoadScrap);
  225.     
  226.     // figure out the scrap type and offset
  227.     scrapResult = GetScrapTypeAndOffset( &validScrapType, &offset );
  228.     
  229.     // setup for the drawing
  230.     TextFont(applFont);
  231.     TextSize(9);
  232.     GetFontInfo(&theInfo);
  233.  
  234.     // caclulate our area at the top to say what type of contents the scrap is
  235.         GetWindowPortBounds(pWindow, &topAreaRect);
  236.     topAreaRect.bottom = topAreaRect.top + theInfo.ascent + theInfo.descent + theInfo.leading * 2 + 2;
  237.  
  238.     if( gMachineInfo.haveAppearanceMgr )
  239.         {
  240.         // draw a Finder-style window header
  241.         Rect placardRect = topAreaRect;
  242.         
  243.         InsetRect( &placardRect, -1, -1 );
  244.         
  245.         DrawThemePlacard( &placardRect, IsWindowHilited(pWindow) ? kThemeStateActive : kThemeStateInactive );
  246.         eraseRect.top = placardRect.bottom + 1;
  247.         }
  248.     else
  249.         {
  250.     // draw two lines under the area to separate it from the rest of the window
  251.     MoveTo(topAreaRect.left, topAreaRect.bottom - 2);
  252.     Line(topAreaRect.right - topAreaRect.left, 0);
  253.     Move(0, 2);
  254.     Line(-(topAreaRect.right - topAreaRect.left), 0);
  255.         }
  256.     
  257.     EraseRect( &eraseRect );
  258.  
  259.     // draw a string describing the contents
  260.     {
  261.     Str255    theString;
  262.     
  263.     switch (validScrapType)
  264.         {
  265.         case 'PICT':
  266.             GetIndString(theString, kClipboardStrings, iClipboardPICT);
  267.             break;
  268.             
  269.         case 'TEXT':
  270.             GetIndString(theString, kClipboardStrings, iClipboardText);
  271.             break;
  272.             
  273.         default:
  274.             if (InfoScrap()->scrapCount == 0)
  275.                 GetIndString(theString, kClipboardStrings, iClipboardNone);
  276.             else
  277.                 GetIndString(theString, kClipboardStrings, iClipboardUnknown);
  278.             break;
  279.         }
  280.         
  281.     MoveTo(topAreaRect.left + 4, topAreaRect.bottom - 4);
  282.  
  283.     // draw in the correct placard text color ••• need to add deviceloop
  284.     if( gMachineInfo.haveAppearanceMgr )
  285.         {
  286.         ThemeTextColor    themeTextColor = kThemeTextColorPlacardActive;
  287.     
  288.         if( ! IsWindowHilited(pWindow) )
  289.             {
  290.             themeTextColor = kThemeTextColorPlacardInactive;
  291.             }
  292.         
  293.         SetThemeTextColor( themeTextColor, 32, true );
  294.         }
  295.     
  296.     DrawString(theString);
  297.     }
  298.     
  299.     // calculate the part *not* in our top area    
  300.     topAreaRect.top = topAreaRect.bottom+1;
  301.         topAreaRect.bottom = GetWindowPortBounds(pWindow, &bounds)->bottom;
  302.  
  303.     // remember the scrap count -- if it changes, we do an update!
  304.     ((ClipboardDataPtr)pData)->scrapCount = InfoScrap()->scrapCount;
  305.  
  306.     // now, draw the contents, if we have a legal type to use
  307.     {
  308.     Rect    clipArea = topAreaRect;
  309.     Handle    scrapHandle = InfoScrap()->scrapHandle;
  310.     
  311.     // scrollbar clear area - Donna doesn’t like this.  She’s right- we have no scrollbars!
  312. //    clipArea.right -= 15;
  313. //    clipArea.bottom -= 15;
  314.     ClipRect(&clipArea);
  315.     switch (validScrapType)
  316.         {
  317.         case 'PICT':
  318.             DrawPictureFromHandleAndOffset(&clipArea, 
  319.                     scrapHandle, offset);
  320.             break;
  321.             
  322.         case 'TEXT':
  323.             {
  324.             char    oldState;
  325.                     
  326.             oldState = HGetState(scrapHandle);
  327.             HLock(scrapHandle);
  328.             clipArea.right -= 15;
  329.             clipArea.bottom -= 15;
  330.             TETextBox(*scrapHandle+offset, scrapResult, &clipArea, teJustLeft);
  331.             }
  332.             break;
  333.         }
  334.     }
  335.     
  336.     // finally draw the grow icon, but omit our top area rect from the drawing
  337.     ClipRect(&topAreaRect);
  338.     DrawGrowIcon(pWindow);
  339.     
  340.     SetClip(oldClip);
  341.     DisposeRgn(oldClip);
  342.     
  343.     UnloadScrap();
  344.     
  345. // FALL THROUGH EXCEPTION HANDLING
  346. LoadScrap:
  347.     return anErr;
  348.     
  349. } // ClipboardUpdateWindow
  350.  
  351.  
  352. // --------------------------------------------------------------------------------------------------------------
  353.  
  354. static Boolean    ClipboardFilterEvent(WindowPtr pWindow, WindowDataPtr pData, EventRecord *pEvent)
  355. {    
  356.  
  357.     // Force an update on scrap changes during activate/deactivate.
  358.  
  359.     switch (pEvent->what)
  360.         {
  361.         case nullEvent:
  362.             if (LoadScrap() == noErr)
  363.             {
  364.             PScrapStuff pScrap = InfoScrap();
  365.  
  366.             if (pScrap->scrapCount != ((ClipboardDataPtr)pData)->scrapCount)
  367.                 {
  368.                 Rect bounds;
  369.                 InvalWindowRect(pWindow, GetWindowPortBounds(pWindow, &bounds));
  370.                 }
  371.             }
  372.             break;
  373.             
  374.         case activateEvt:
  375.                 {
  376.                 Rect bounds;
  377.                 InvalWindowRect(pWindow, GetWindowPortBounds(pWindow, &bounds));
  378.                 }
  379.             break;
  380.         
  381.         // Follow the HI guidelines and hide the clipboard when we are suspended.
  382.     
  383.         case osEvt:
  384.             if (((pEvent->message >> 24) & 0x0FF) == suspendResumeMessage)
  385.                 {
  386.                 if((pEvent->message & resumeFlag)==0)    // suspending
  387.                     {
  388.                     HideWindow(pWindow);
  389.                     pWindow = FrontWindow();
  390.                     if (pWindow)
  391.                         HiliteWindow(pWindow, false);
  392.                     }
  393.                 else                                    // resuming
  394.                     ShowWindow(pWindow);
  395.                 }
  396.             break;
  397.             
  398.         } // switch(what)
  399.     
  400.     return false;
  401.     
  402. } // ClipboardFilterEvent
  403.  
  404.  
  405. // --------------------------------------------------------------------------------------------------------------
  406.  
  407. static OSErr    ClipboardKeyEvent(WindowPtr pWindow, WindowDataPtr pData, EventRecord *pEvent, Boolean isMotionKey)
  408. {    
  409.     #pragma unused(pWindow, pData, pEvent, isMotionKey)
  410.  
  411.     return noErr;
  412.  
  413. } // ClipboardKeyEvent
  414.  
  415.  
  416. // --------------------------------------------------------------------------------------------------------------
  417.  
  418. static OSErr    ClipboardGetBalloon(WindowPtr pWindow, WindowDataPtr pData, 
  419.         Point *localMouse, short * returnedBalloonIndex, Rect *returnedRectangle)
  420. {
  421. #pragma unused (pWindow, pData, localMouse, returnedRectangle)
  422.  
  423.     *returnedBalloonIndex = iNoBalloon;
  424.     
  425.     return noErr;
  426.  
  427. } // ClipboardGetBalloon
  428.  
  429. // --------------------------------------------------------------------------------------------------------------
  430.  
  431. static OSErr    ClipboardGetDocumentRect(WindowPtr pWindow, WindowDataPtr pData, 
  432.             LongRect * documentRectangle, Boolean forGrow)
  433. {
  434. #pragma unused (pWindow, pData, forGrow)
  435.     
  436.     OSType    scrapType = 0;
  437.     long    sourceOffset;
  438.     Rect    theMaxSize;
  439.     
  440.     // default to size of main screen (••• sucks for text)
  441.     GetPixBounds( (**GetMainDevice()).gdPMap, &theMaxSize );
  442.     
  443.     GetScrapTypeAndOffset( &scrapType, &sourceOffset );
  444.     
  445.     //
  446.     // We know the size of a picture, man.
  447.     //
  448.     if( scrapType == 'PICT' )
  449.     {
  450.         if( LoadScrap() == noErr )
  451.         {
  452.             Handle        sourceHandle = InfoScrap()->scrapHandle;
  453.             PicPtr        pPicture;
  454.             FontInfo    theInfo;
  455.         
  456.             pPicture = (PicPtr)((*sourceHandle) + sourceOffset);
  457.             theMaxSize.right = pPicture->picFrame.right - pPicture->picFrame.left;
  458.             theMaxSize.bottom = pPicture->picFrame.bottom - pPicture->picFrame.top;
  459.             
  460.             //
  461.             // add window header size
  462.             //
  463.             TextFont(applFont);
  464.             TextSize(9);
  465.             GetFontInfo( &theInfo );
  466.             
  467.             theMaxSize.bottom += theInfo.ascent + theInfo.descent + theInfo.leading * 2 + 2;
  468.             
  469.             //
  470.             // add width for scrollbars (••• which don’t exist)
  471.             //
  472. //            theMaxSize.bottom += 15;
  473. //            theMaxSize.right += 15;
  474.             
  475.             UnloadScrap();
  476.         }
  477.  
  478.     }
  479.  
  480.     RectToLongRect(&theMaxSize, documentRectangle);
  481.     
  482.     return noErr;
  483.     
  484. } // ClipboardGetDocumentRect
  485.  
  486.  
  487. // --------------------------------------------------------------------------------------------------------------
  488.  
  489. static OSErr    ClipboardCloseWindow(WindowPtr pWindow, void* refCon)
  490. {    
  491. #pragma unused(pWindow,refCon)
  492.  
  493.     ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardShow);
  494.     UnloadScrap();
  495.     
  496.     return noErr;
  497.  
  498. } // ClipboardCloseWindow
  499.  
  500.  
  501. // --------------------------------------------------------------------------------------------------------------
  502.  
  503. static OSErr    ClipboardMakeWindow(WindowPtr pWindow, WindowDataPtr pData)
  504. {
  505. #pragma unused (pWindow)
  506.     BitMap bitmap;
  507.  
  508.     pData->hasGrow                 = true;
  509.     pData->pFilterEvent         = (FilterEventProc)     ClipboardFilterEvent;
  510.     pData->pKeyEvent            = (KeyEventProc)         ClipboardKeyEvent;
  511.     pData->pGetBalloon            = (GetBalloonProc)         ClipboardGetBalloon;
  512.     pData->pUpdateWindow         = (UpdateWindowProc)     ClipboardUpdateWindow;
  513.     pData->pGetDocumentRect     = (GetDocumentRectProc) ClipboardGetDocumentRect;
  514.     pData->pCloseWindow            = (CloseWindowProc)        ClipboardCloseWindow;
  515.     
  516.     GetQDGlobalsScreenBits(&bitmap);
  517.     pData->contentRect.right = pData->contentRect.left + 
  518.                     bitmap.bounds.right - 
  519.                     bitmap.bounds.left - 96;
  520.     pData->contentRect.bottom = pData->contentRect.top + 150;
  521.     MoveWindow(pWindow, bitmap.bounds.left + 4, 
  522.             bitmap.bounds.bottom - 154, false);
  523.     
  524.     ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardHide);
  525.  
  526.     return noErr;
  527.     
  528. } // ClipboardMakeWindow
  529.  
  530.  
  531. // --------------------------------------------------------------------------------------------------------------
  532.  
  533. OSErr    ClipboardPreflightWindow(PreflightPtr pPreflightData)
  534. {    
  535.     pPreflightData->resourceID            = kClipboardWindowID;
  536.     pPreflightData->continueWithOpen     = true;
  537.     pPreflightData->makeProcPtr         = ClipboardMakeWindow;
  538.     pPreflightData->storageSize         = sizeof(ClipboardDataRecord);
  539.     
  540.     return noErr;
  541.     
  542. } // ClipboardPreflightWindow
  543.  
  544. // --------------------------------------------------------------------------------------------------------------
  545.  
  546. void ClipboardGetFileTypes(OSType * pFileTypes, OSType * pDocumentTypes, short * numTypes)
  547. {
  548. #pragma unused (pFileTypes, pDocumentTypes, numTypes)
  549.  
  550. } // ClipboardGetFileTypes
  551.